﻿using System.Collections.Generic;
using UnityEngine;

public class MockClient : MonoBehaviour
{
    public static MockClient instance;
    public static uint remoteEstimatedFrame = 0;  //客户端估计服务端的帧号，会根据服务端进行调整
    public static bool hasReceivedState = false;
    public static uint delay;  //会根据服务端的数据改变而改变
    public static int minDiff;
    public static int maxDiff;
    [SerializeField]
    private BallMotor localBallMotor;
    [SerializeField]
    public NetPosComponent clientNetBall;
    public NetPosComponent[] clientNetObjects;

    private void Awake()
    {
        instance = this;
    }
    private void FixedUpdate()
    {
        if (hasReceivedState)
        {
            float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");
            var move = (v * Vector3.forward + h * Vector3.right).normalized;
            MockServer.instance.SendCommandToServer(remoteEstimatedFrame, move);
            localBallMotor.LocalMove(remoteEstimatedFrame, move);
            foreach (var netObject in clientNetObjects)
            {
                netObject.Simulate(remoteEstimatedFrame);
            }
            remoteEstimatedFrame += 1;
        }
    }

    public void SyncServerInitSucess(uint serverSendRate)
    {
        remoteEstimatedFrame = 0;
        delay = serverSendRate;
        minDiff = (int)delay - 5;
        maxDiff = (int)delay + 5;
        hasReceivedState = true;
    }

    public void SyncServerDataToClient(uint serverFrame, uint lastVerifiedClientFrame, List<Vector3> positionList, List<Vector3> velocityList)
    {
        //调整客户端和服务端的帧号，让它们一直保持有N帧的差异
        AdjustRemoteEstimatedFrame(serverFrame);
        //每次收到服务端的状态，都进行回滚
        RollBack(lastVerifiedClientFrame, positionList, velocityList);
    }

    public void S2CSyncPos(uint serverFrame, Vector3[] posList)
    {
        for (int index = 0; index < posList.Length; index++)
        {
            clientNetObjects[index].SyncPos(serverFrame, posList[index]);
        }
    }

    public void RollBack(uint lastVerifiedClientFrame, List<Vector3> verifiedPositionList, List<Vector3> verifiedVelocityList)
    {
        Vector3 verifiedPosition = verifiedPositionList[0];
        Vector3 veriedVelocity = verifiedVelocityList[0];
        //然后执行该帧后玩家所有的操作指令
        localBallMotor.RollBack(lastVerifiedClientFrame, verifiedPosition, veriedVelocity);
    }

    public static void AdjustRemoteEstimatedFrame(uint serverFrame)
    {
        //若相差巨大，则调整
        int remoteDiffFrame = (int)serverFrame - (int)remoteEstimatedFrame;
        if (remoteDiffFrame < minDiff || remoteDiffFrame > maxDiff)
        {
            print(string.Format("AdjustRemoteEstimatedFrame, serverFrame:{0}, clientFrame:{1}", serverFrame, remoteEstimatedFrame));
            remoteEstimatedFrame = serverFrame - delay;
        }
    }
}
